package tuanda.soict.firstsun.LogicPackage;

import tuanda.soict.firstsun.AbilityPackage.Ability;
import tuanda.soict.firstsun.BuildingPackage.Army_Building;
import tuanda.soict.firstsun.BuildingPackage.Building;
import tuanda.soict.firstsun.BuildingPackage.Gold_Building;
import tuanda.soict.firstsun.BuildingPackage.HP_Building;
import tuanda.soict.firstsun.BuildingPackage.HQ_Building;
import tuanda.soict.firstsun.DataPackage.CommonConstants;

/**
 * @author tuanda_soict_hut
 * @version 0.0.7
 * @since 4-9-2012
 */
public class Group implements Controllable, CommonConstants {

	private static int numberGroup = 0;
	private Army[] armyStatus;
	private Building[] buildingStatus;
	private int numberArmy;
	private int numberBuilding;
	private int groupID;
	private String groupName;
	private int side;
	private HQ_Building hq_building;
	private boolean isLost;
	private int income;
	private StrategyInfomation strategyInfomation;
	private int type;

	public Group(String name, int side, int id, int incom, int type) {
		if (getNumberGroup() < DEFAULT_MAX_GROUP) {
			setID(id);
			setName(name);
			setSide(side);
			armyStatus = new Army[DEFAULT_MAX_ARMY_PER_GROUP];
			buildingStatus = new Building[DEFAULT_MAX_BUILDING_PER_GROUP];
			setNumberArmy(GROUP_EXIST);
			setNumberBuilding(GROUP_EXIST);
			setNumberGroup(getNumberGroup() + 1);
			setLost(false);
			setIncome(incom);
			setType(type);
			setStrategyInfomation(new StrategyInfomation());
		}
	}

	public final static void resetGroupNumber() {
		numberGroup = 0;
	}

	public final int getType() {
		return this.type;
	}

	public final void setType(int typ) {
		this.type = typ;
	}

	public final void setStrategyInfomation(StrategyInfomation strategy) {
		this.strategyInfomation = strategy;
	}

	public final StrategyInfomation getStrategyInfomation() {
		return this.strategyInfomation;
	}

	public final int getIncome() {
		return this.income;
	}

	public final void setIncome(int inc) {
		if (inc > -1) {
			this.income = inc;
		} else {
			this.income = 0;
		}
	}

	public final boolean isLost() {
		return this.isLost;
	}

	public final void setLost(boolean lost) {
		this.isLost = lost;
	}

	@Override
	public final String getName() {
		return this.groupName;
	}

	@Override
	public final void setName(String nam) {
		this.groupName = nam;
	}

	@Override
	public final int getID() {
		return this.groupID;
	}

	@Override
	public final void setID(int id) {
		this.groupID = id;
	}

	public final HQ_Building getHQBuilding() {
		return this.hq_building;
	}

	public final Building setHqBuilding(HQ_Building building) {
		this.hq_building = building;
		return building;
	}

	public final void removeHQBuilding() {
		this.hq_building = null;
	}

	public final int getSide() {
		return this.side;
	}

	public final void setSide(int sid) {
		this.side = sid;
	}

	public static int getNumberGroup() {
		return numberGroup;
	}

	public static void setNumberGroup(int numGroup) {
		numberGroup = numGroup;
	}

	public static void decreaseNumberGroup() {
		numberGroup--;
	}

	public static void increaseNumberGroup() {
		numberGroup++;
	}

	public final Army addInitialArmy(String nam, int ran, int typ, int minAtk,
			int maxAtk, int def, int mov, int range, int gold, int x, int y,
			int dataID, Ability[] ability, int attr) {
		if (numberArmy != GROUP_NOT_EXIST
				&& numberArmy < DEFAULT_MAX_ARMY_PER_GROUP) {
			for (int i = 0; i < DEFAULT_MAX_ARMY_PER_GROUP; i++) {
				if (armyStatus[i] == null) {
					armyStatus[i] = new Army(nam, i, getID(), ran, minAtk,
							maxAtk, def, mov, range, typ, gold, x, y, dataID,
							ability, attr);
					numberArmy++;
					return armyStatus[i];
				}
			}
			return null;
		} else {
			return null;
		}
	}

	public final Army addArmy(String nam, int ran, int typ, int minAtk,
			int maxAtk, int def, int mov, int range, int gold, int x, int y,
			int dataID, Ability[] ability, int attr) {
		if (this.getIncome() >= gold) {
			if (numberArmy != GROUP_NOT_EXIST
					&& numberArmy < DEFAULT_MAX_ARMY_PER_GROUP) {
				for (int i = 0; i < DEFAULT_MAX_ARMY_PER_GROUP; i++) {
					if (armyStatus[i] == null) {
						armyStatus[i] = new Army(nam, i, getID(), ran, minAtk,
								maxAtk, def, mov, range, typ, gold, x, y,
								dataID, ability, attr);
						numberArmy++;
						this.setIncome(getIncome() - gold);
						return armyStatus[i];
					}
				}
				return null;
			} else {
				return null;
			}
		} else {
			return null;
		}
	}

	public final Building addBuilding(String nam, int def, int obsPoint,
			int typ, int x, int y, int dataID) {
		if (numberBuilding != GROUP_NOT_EXIST
				&& numberBuilding < DEFAULT_MAX_BUILDING_PER_GROUP) {
			for (int i = 0; i < DEFAULT_MAX_BUILDING_PER_GROUP; i++) {
				if (buildingStatus[i] == null) {
					buildingStatus[i] = new Building(nam, def, i, getID(),
							obsPoint, typ, x, y, dataID);
					numberBuilding++;
					return buildingStatus[i];
				}
			}
			return null;
		} else {
			return null;
		}
	}

	public final Building addGoldBuilding(String nam, int def, int obsPoint,
			int typ, int goldProd, int x, int y, int dataID) {
		if (numberBuilding != GROUP_NOT_EXIST
				&& numberBuilding < DEFAULT_MAX_BUILDING_PER_GROUP) {
			for (int i = 0; i < DEFAULT_MAX_BUILDING_PER_GROUP; i++) {
				if (buildingStatus[i] == null) {
					buildingStatus[i] = new Gold_Building(nam, def, i, getID(),
							obsPoint, typ, goldProd, x, y, dataID);
					numberBuilding++;
					return buildingStatus[i];
				}
			}
			return null;
		} else {
			return null;
		}
	}

	public final Building addHPBuilding(String nam, int def, int obsPoint,
			int category, int goldProd, int hp, int x, int y, int dataID) {
		if (numberBuilding != GROUP_NOT_EXIST
				&& numberBuilding < DEFAULT_MAX_BUILDING_PER_GROUP) {
			for (int i = 0; i < DEFAULT_MAX_BUILDING_PER_GROUP; i++) {
				if (buildingStatus[i] == null) {
					buildingStatus[i] = new HP_Building(nam, def, i, getID(),
							obsPoint, category, goldProd, hp, x, y, dataID);
					numberBuilding++;
					return buildingStatus[i];
				}
			}
			return null;
		} else {
			return null;
		}
	}

	public final Building addArmyBuilding(String nam, int def, int obsPoint,
			int typ, int goldProd, int hp, int type, int x, int y, int dataID) {
		if (numberBuilding != GROUP_NOT_EXIST
				&& numberBuilding < DEFAULT_MAX_BUILDING_PER_GROUP) {
			for (int i = 0; i < DEFAULT_MAX_BUILDING_PER_GROUP; i++) {
				if (buildingStatus[i] == null) {
					buildingStatus[i] = new Army_Building(nam, def, i, getID(),
							obsPoint, typ, goldProd, hp, type, x, y, dataID);
					numberBuilding++;
					return buildingStatus[i];
				}
			}
			return null;
		} else {
			return null;
		}
	}

	public final void removeArmy(int id) {
		if (numberArmy > GROUP_EXIST) {
			if (id > -1 && id < DEFAULT_MAX_ARMY_PER_GROUP) {
				armyStatus[id] = null;
				numberArmy--;
			}
		}
	}

	public final void removeBuilding(int id) {
		if (numberBuilding > GROUP_EXIST) {
			if (id > -1 && id < DEFAULT_MAX_BUILDING_PER_GROUP) {
				buildingStatus[id] = null;
				numberBuilding--;
			}
		}
	}

	public final int getNumberArmy() {
		return numberArmy;
	}

	public final void setNumberArmy(int numArmy) {
		this.numberArmy = numArmy;
	}

	public final int getNumberBuilding() {
		return numberBuilding;
	}

	public final void setNumberBuilding(int numBuilding) {
		this.numberBuilding = numBuilding;
	}

	public final void setArmy(int id, Army arm) {
		if (id > -1 && id < armyStatus.length) {
			armyStatus[id] = arm;
		}
	}

	public final Army[] getArmy() {
		return this.armyStatus;
	}

	public final Army getArmy(int id) {
		if (id > -1 && id < DEFAULT_MAX_ARMY_PER_GROUP) {
			return armyStatus[id];
		} else {
			return null;
		}
	}

	public final void setBuilding(int id, Building build) {
		if (id > -1 && id < buildingStatus.length) {
			buildingStatus[id] = build;
		}
	}

	public final void setGoldBuilding(int id, Gold_Building build) {
		if (id > -1 && id < buildingStatus.length) {
			buildingStatus[id] = build;
		}
	}

	public final void setHPBuilding(int id, HP_Building build) {
		if (id > -1 && id < buildingStatus.length) {
			buildingStatus[id] = build;
		}
	}

	public final void setArmyBuilding(int id, Army_Building build) {
		if (id > -1 && id < buildingStatus.length) {
			buildingStatus[id] = build;
		}
	}

	public final Building[] getBuilding() {
		return this.buildingStatus;
	}

	public final Building getBuilding(int id) {
		if (id > -1 && id < DEFAULT_MAX_ARMY_PER_GROUP) {
			return buildingStatus[id];
		} else {
			return null;
		}
	}

	public final void healArmy(BattleMap map) {
		int x, y;
		for (int i = 0; i < armyStatus.length; i++) {
			if (armyStatus[i] != null) {
				x = armyStatus[i].getLocationX();
				y = armyStatus[i].getLocationY();
				if (map.getBuilding(x, y) != null) {
					Building building = map.getBuilding(x, y);
					if (building.getGroupID() == getID()
							&& building.getBuildingType() > PRODUCE_GOLD_TYPE) {
						armyStatus[i].setHealth(armyStatus[i].getHealth()
								+ ((HP_Building) building).getHPRestore());
					}
				}
			}
		}
	}

	public final int calculateIncomePerDay() {
		int gold = 0;
		if (hq_building.getTurnsBeforeLost() == MANY_TURNS) {
			gold += hq_building.getGoldProduce();
		}
		for (int i = 0; i < buildingStatus.length; i++) {
			if (buildingStatus[i] != null) {
				if (buildingStatus[i].getBuildingType() > UNKNOWN_TYPE) {
					gold += ((Gold_Building) buildingStatus[i])
							.getGoldProduce();
				}
			}
		}
		return gold;
	}

	public final int produceGold(BattleMap map) {
		int gold = calculateIncomePerDay();
		setIncome(getIncome() + gold);
		return gold;
	}

	public final void decreaseDayToDeath() {
		if (hq_building.getTurnsBeforeLost() != MANY_TURNS) {
			hq_building
					.setTurnsBeforeLost(hq_building.getTurnsBeforeLost() - 1);
			if (hq_building.getTurnsBeforeLost() == 0) {
				this.setLost(true);
			}
		}
	}

	public final void preMainPhase(BattleMap map) {
		produceGold(map);
		healArmy(map);
	}

	public final void postMainPhase() {
		decreaseDayToDeath();
	}
}
